#include "IteradorBloques.h"
#include "EstrategiaAlmacenamientoBloques.h"
#include "../Bytes.h"
#include "../componentes/Bloque.h"
#include "../componentes/RegistroVariable.h"
#include "../componentes/Compuesto.h"
#include "../recursoDeAlmacenamiento/FabricaCompuestos.h"

IteradorBloques::IteradorBloques(EstrategiaAlmacenamientoBloques* estrategia) {
	this->estrategia = estrategia;
	this->bloqueActual = NULL;

	this->reiniciarIterador();

}

IteradorBloques::~IteradorBloques() {

	if (this->bloqueActual != NULL) {
		delete this->bloqueActual;
	}
}


Bytes IteradorBloques::getSiguiente() {

	if (!tieneSiguiente()) {
		return Bytes("");
	}

	while (itBloqueActual == this->listaRegistros.end() && (offsetActual != estrategia->recurso->getTamanioArchivo())) {
		levantarBloque();
	}

	RegistroVariable* registro = (RegistroVariable*)(*itBloqueActual);
	itBloqueActual++;
	return registro->getDato();
}

bool IteradorBloques::tieneSiguiente() {
	return !((itBloqueActual == this->listaRegistros.end()) && (offsetActual == estrategia->recurso->getTamanioArchivo()) );
}

void IteradorBloques::reiniciarIterador() {

	this->itBloqueActual = this->listaRegistros.end();
	this->offsetActual = this->estrategia->tamanioHeaderConPadding;

	if (tieneSiguiente()) {
		levantarBloque();
	}
}

bool IteradorBloques::levantarBloque() {

	cantBytes tamanioBloque = estrategia->tamanioBloque;

	Bytes bytesBloque = estrategia->recurso->leer(this->offsetActual, tamanioBloque);

	if (bytesBloque.estaVacio()) {
		itBloqueActual = listaRegistros.end();
		return false;
	}

	if (this->bloqueActual != NULL) {
		delete this->bloqueActual;
	}

	this->bloqueActual = this->estrategia->recurso->fabrica->crearCompuesto(tamanioBloque);
	this->bloqueActual->hidratarse(bytesBloque);

	this->offsetActual += tamanioBloque;
	this->listaRegistros = this->bloqueActual->getComponentes();

	this->itBloqueActual = this->listaRegistros.begin();

	return true;
}

offset IteradorBloques::getNumBloqueActual() {
	return  ((this->offsetActual - estrategia->tamanioHeaderConPadding) / estrategia->tamanioBloque) - 1;
}
